<template>
  <div class="event-dock-container">
    <el-collapse v-if="editable" v-model="cmpWidget.expandedEvent">
      <!--组件属性-->
      <el-collapse-item title="组件变量" name="attribute">
        <div class="pad-lft-rgt-10">
          <div class="mar-btm">
            <div class="flex-justify-start wrap mar-btm">
              <div v-for="value in defaultPortValue" :key="value.key" class="mar-rgt-5">
                <span class="font-weight-bold">{{value.name}}</span>
                <span> ({{value.key}});</span>
              </div>
            </div>
            <el-divider></el-divider>
          </div>
          <draggable v-model="dragVarList" @end="onDragPortEnd" handle=".drag-mover">
            <transition-group>
              <div v-for="(variable, idx) in dragVarList" :key="variable.key" class="mar-btm">
                <div class="flex-com mar-btm">
                  <div class="label-title font-weight-bold drag-mover cursor-pointer">变量名</div>
                  <el-input v-model="variable.name" size="mini" placeholder="请输入变量名"></el-input>
                  <span class="el-icon-delete cursor-pointer font-hover-danger"
                        @click="deleteVariable(variable)"></span>
                </div>
                <div class="flex-com mar-btm">
                  <span class="label-title">KEY</span>
                  <el-input class="state-input" v-model="variable.editKey" :disabled="isEditKey"
                            size="mini"
                            clearable @blur="checkKey(idx,variable.editKey)"></el-input>
                  <el-tooltip effect="dark" content="编辑" placement="top">
                    <i class="el-icon-edit cursor-pointer font-weight-bold font-hover-primary mar-lft-10"
                       @click="isEditKey=false"></i>
                  </el-tooltip>
                  <el-tooltip effect="dark" content="复制" placement="top">
                    <i
                      class="el-icon-copy-document cursor-pointer font-weight-bold font-hover-primary mar-lft-10"
                      @click="copyDomText(variable.editKey)"></i>
                  </el-tooltip>
                </div>
                <div class="flex-com mar-btm">
                  <div class="label-title">值类型</div>
                  <el-select v-model="variable.type" size="mini" placeholder="请选择变量类型" class="width-100"
                             @change="variableTypeChange(variable)">
                    <el-option v-for="dataTyp in dataTypeArray" :key="dataTyp.value" :label="dataTyp.label"
                               :value="dataTyp.value"></el-option>
                  </el-select>
                </div>
                <div class="flex-com mar-btm">
                  <div class="label-title">默认值</div>
                  <VariableComponent :variable="variable"></VariableComponent>
                </div>
                <el-divider></el-divider>
              </div>
            </transition-group>
          </draggable>
          <div class="font-color-primary font-size-12 font-weight-bold">
            <div class="display-inline cursor-pointer" @click="addVariable">
              <i class="iconfont icon-tianjia"></i><span class="mar-lft-5">添加变量</span>
            </div>
          </div>
        </div>
      </el-collapse-item>
      <div class="color-gray-96" style="height: 10px"></div>
      <!--组件自带事件-->
      <el-collapse-item v-for="(event, idx) in systemEventValue" :key="idx" :name="`${event.eventType}${idx}`">
        <div slot="title" class="flex-justify-between width-100">
          <div>{{eventName(event)}}</div>
<!--          <div class="font-color-danger cursor-pointer" @click.stop="deleteCustomEvent(event)">-->
<!--            <i class="el-icon-delete font-size-18 font-hover-bold"></i>-->
<!--          </div>-->
        </div>
        <div class="pad-lft-rgt-10">
          <div class="flex-com mar-btm" v-if="event.eventType==='longPress' && event.value">
            <span class="label-title" style="width: 100px;">长按时间(s)</span>
            <el-input-number v-model="event.value.time" :step="1" :min="0"
              size="mini" class="width-input"></el-input-number>
          </div>
          <!---事件下的行为-->
          <ActionComponent :relAction="event.action" :widget="cmpWidget"
                           @dragEvent="(val) =>dragEvent(val,event)"></ActionComponent>
        </div>
      </el-collapse-item>

      <!--组件自定义事件-->
      <draggable v-model="dragEventList" @end="onDragEventEnd" handle=".drag-evn-mover">
        <transition-group>
          <el-collapse-item v-for="(event, idx) in dragEventList" :key="event.key" :name="`${event.eventType}${idx}`">
            <div slot="title" class="flex-justify-between width-100">
              <div class="drag-evn-mover">{{eventName(event)}}</div>
              <div v-if="event.eventType === 'custom'" class="flex-justify-end pad-rgt-5">
                <div class="font-color-danger cursor-pointer" @click.stop="deleteCustomEvent(event)">
                  <i class="el-icon-delete font-size-18 font-hover-bold"></i>
                </div>
                <div class="font-color-primary cursor-pointer mar-lft-10" @click.stop="editCustomEvent(event)">
                  <i class="el-icon-edit-outline font-size-18 font-hover-bold"></i>
                </div>
              </div>
            </div>
            <div class="pad-lft-rgt-10">
              <!---事件下的行为-->
              <ActionComponent :relAction="event.action" :widget="cmpWidget"
                               @dragEvent="(val) =>dragEvent(val,event)"></ActionComponent>
            </div>
          </el-collapse-item>
        </transition-group>
      </draggable>

      <div class="font-color-primary font-size-12 font-weight-bold pad-all-10">
        <div class="display-inline cursor-pointer" @click="addCustomEvent">
          <i class="iconfont icon-tianjia"></i><span class="mar-lft-5">添加自定义事件</span>
        </div>
      </div>
    </el-collapse>
    <EmptyContent v-else :empty-text="editableMsg" :min-height="400" :image-size="140"></EmptyContent>
    <el-dialog title="自定义事件" :visible.sync="showCustomEventDialog" width="500px"  :close-on-click-modal="false">
      <el-form :ref="customEventFormRef" :model="customEventForm" :rules="customEventFormRules" size="medium"
               label-width="80px">
        <el-form-item label="事件名称" prop="name">
          <el-input v-model="customEventForm.name" placeholder="请填写事件名称"></el-input>
        </el-form-item>
        <div class="mar-top text-align-right">
          <el-button type="info" @click="showCustomEventDialog = false">取消</el-button>
          <el-button type="primary" @click="customEventFormSubmit">提交</el-button>
        </div>
      </el-form>
    </el-dialog>
  </div>
</template>

<script>
  import EmptyContent from "@/components/IDE/EmptyContent.vue";
  import {mapState} from "vuex";
  import {confirmHandle, copyDomText, deepCopy, generateUID, messageHandle} from "@/utils";
  import {WidgetClass} from "@/modules/IDE/widget/atom/widget";
  import ActionComponent from "./component/ActionComponent.vue";
  import {dataTypeArray} from "@/config/common";
  import {WidgetFactory} from "@/modules/IDE/widgetFactory";
  import VariableComponent from "./component/VariableComponent.vue";
  import draggable from 'vuedraggable'

  export default {
    name: "EventDock",
    props: {
      widget: {
        type: WidgetClass,
        default: () => {
          return {};
        },
      },
    },
    components: {
      EmptyContent, ActionComponent, VariableComponent, draggable
    },
    data() {
      return {
        editableMsg: '',
        dataTypeArray: dataTypeArray,
        showCustomEventDialog: false,
        isEditCustomEvent: false,
        customEventFormRules: {
          name: [
            {required: true, message: '请填写事件名称', trigger: ['blur', 'change']}
          ],
        },
        customEventForm: {},
        customEventFormRef: 'customEventFormRef',
        dragVarList: [],
        dragEventList: [],
        isEditKey: true
      };
    },
    computed: {
      ...mapState({
        globalVarList: (state) => state.ide.globalVarList,
        globalScenesList: (state) => state.ide.globalScenesList,
      }),
      editable() {
        // 自定义组件的操作中所有组件都能编辑
        if (this.editorType === 'component') return true;
        // 子页面关联组件不可编辑
        if (this.widget.relateSubPage) {
          this.editableMsg = '请前往子页面进行编辑';
          return false;
        }
        return true;
      },
      cmpWidget() {
        // 如果组件的父组件是 TabBar，则点击组件后显示父组件的事件
        return !this.isParentTabBar ? this.widget : this.widgetParent;
      },
      widgetParent() {
        return WidgetFactory.getWidgetById(this.widget.parentId);
      },
      isParentTabBar() {
        if (!this.widget.parentId) return false;
        if (!this.widgetParent) return false;
        return ['tabBarPage','pageView'].includes(this.widgetParent.category)
      },
      eventName() {
        return (event = {}) => {
          const {eventType, name = ''} = event;
          if (eventType === 'custom') return name;
          if (name.includes('事件')) return name;
          return `${name}事件`;
        }
      },
      defaultPortValue() {
        const defaultValue = [];
        this.cmpWidget.ports.values.forEach(val => {
          !val.custom && defaultValue.push(val);
        });
        return defaultValue;
      },
      customPortValue() {
        const customValue = [];
        let values = this.cmpWidget.ports.values
        values.forEach(val => {
          val.custom && customValue.push(val);
        });
        return customValue;
      },
      customEventValue() {
        const customEnvValue = [];
        let values = this.cmpWidget.ports.events
        values.forEach(val => {
          val.eventType === 'custom' && customEnvValue.push(val);
        });
        return customEnvValue;
      },
      systemEventValue() {
        const systemValue = [];
        let values = this.cmpWidget.ports.events
        values.forEach(val => {
          val.eventType !== 'custom' && systemValue.push(val);
        });
        return systemValue;
      },
    },
    watch: {
      customPortValue: {
        handler(val) {
          this.dragVarList = val;
        },
        deep: true,
        immediate: true
      },
      customEventValue: {
        handler(val) {
          this.dragEventList = val;
        },
        deep: true,
        immediate: true
      },
    },
    methods: {
      onDragPortEnd() {
        this.$emit('dragEvent', this.dragVarList);
        const arr = this.cmpWidget.ports.values.filter(item => {
          return !item.custom
        })
        arr.push(...this.dragVarList)
        this.cmpWidget.ports.values = arr
      },
      onDragEventEnd() {
        this.$emit('dragEvent', this.dragEventList);
        const arr = this.cmpWidget.ports.events.filter(item => {
          return item.eventType !== 'custom'
        })
        arr.push(...this.dragEventList)
        this.cmpWidget.ports.events = arr
      },
      copyDomText: copyDomText,
      // 自定义变量相关
      addVariable() {
        let conditions = this.cmpWidget.ports.values
        let lastValue = conditions[conditions.length - 1] ? conditions[conditions.length - 1] : {}
        if (lastValue.name.length === 0) {
          this.$notify({
            message: '请填写变量名',
            type: 'warning',
            duration: 3000,
          });
          return
        }
        const newKey = generateUID();
        this.cmpWidget.ports.values.push({
          name: '',
          type: 'string',
          key: newKey,
          editKey: newKey,
          value: '',
          custom: true
        });
      },
      deleteVariable(variable) {
        const deleteFunc = () => {
          const idx = this.cmpWidget.ports.values.findIndex(val => val.key === variable.key);
          !!~idx && this.cmpWidget.ports.values.splice(idx, 1);
          messageHandle({type: 'success', msg: '变量删除成功！'});
        };
        if (!variable.name) {
          deleteFunc();
        } else {
          confirmHandle({label: `确定要删除变量${variable.name}吗?`}).then(() => {
            deleteFunc();
          }).catch(() => {
          });
        }
      },
      variableTypeChange(variable) {
        switch (variable.type) {
          case 'string':
            variable.value = '';
            break;
          case 'int':
            variable.value = 0;
            break;
          case 'double':
            variable.value = 0;
            break;
          case 'bool':
            variable.value = false;
            break;
          case 'list':
            variable.value = "[]";
            break;
          case 'map':
            variable.value = "{}"
            break;
          default:
            break;
        }
      },
      // 自定义事件相关
      resetCustomEventForm() {
        this.customEventForm = {name: ''};
        const customEventForm = this.$refs[this.customEventFormRef];
        customEventForm && customEventForm.resetFields();
      },
      addCustomEvent() {
        this.resetCustomEventForm();
        this.isEditCustomEvent = false;
        this.showCustomEventDialog = true;
      },
      customEventFormSubmit() {
        this.$refs[this.customEventFormRef].validate((valid) => {
          if (!valid) return;
          if (!this.isEditCustomEvent) {
            this.cmpWidget.ports.events.push({
              name: this.customEventForm.name,
              key: `custom-${generateUID(5)}-${this.cmpWidget.id}`,
              eventType: "custom",
              type: "event",
              action: [],
            });
          } else {
            const event = this.cmpWidget.ports.events.find(e => e.key === this.customEventForm.key);
            event && (event.name = this.customEventForm.name);
          }
          this.showCustomEventDialog = false;
        });
      },
      editCustomEvent(event) {
        this.customEventForm = deepCopy(event);
        this.isEditCustomEvent = true;
        this.showCustomEventDialog = true;
      },
      deleteCustomEvent(event) {
        const idx = this.cmpWidget.ports.events.findIndex(val => val.key === event.key);
        confirmHandle({label: `确定要删除事件：${event.name} 吗?`}).then(() => {
          !!~idx && this.cmpWidget.ports.events.splice(idx, 1);
          messageHandle({type: 'success', msg: '事件删除成功！'});
        }).catch(() => {
        });
      },
      dragEvent(val, event) {
        event.action = val
      },
      checkKey(idx, key) {
        const portValue = [...this.customPortValue, ...this.defaultPortValue]
        const newArr = portValue.map(item => item.key);
        const isRepeat = newArr.some((item, index, arr) => arr.indexOf(item) != index);
        if (isRepeat) {
          this.customPortValue[idx].key = ''
          this.$notify({
            message: 'key值重复，请重新填值',
            type: 'warning',
            duration: 3000,
          });
        }
        this.isEditKey = true
      }
    },
  };
</script>

<style lang="less" scoped>
  .event-dock-container {
    height: calc(100vh - 90px);
    overflow: auto;

    .pad-divider {
      padding: 20px 10px;
      box-sizing: border-box;
      border-bottom: 1px solid #dadce5;
    }

    .title {
      margin: 0;
      color: @colorGray10;
      font-size: 14px;
    }

    .flex-com {
      display: flex;
      align-items: center;
      gap: 10px;
    }

    .wrap {
      flex-wrap: wrap;
      gap: 2px;
    }

    .small-title {
      font-size: 16px;
      color: #666;
      margin: 10px 0;
    }

    .label-title {
      min-width: 42px;
      color: #12131A;
      font-size: 14px;
      text-align: center;
    }

    .state-input {
      /deep/ .el-input__inner {
        background: #f7f8fa;
        border: none;
        outline: none;
      }
    }

    .width-input {
      width: 100%;

      /deep/ .el-input__inner {
        background: #f7f8fa;
      }
    }

    /deep/ .el-collapse {
      .el-collapse-item__header {
        padding-left: 10px !important;
        font-size: 14px;
      }

      .el-collapse-item__content {
        padding-bottom: 10px !important;
      }
    }

    &::-webkit-scrollbar {
      display: none;
    }
  }
</style>
